#define RUNTIME_DBG_LVL			0
#include <dbg/ptest.h>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>

#include <metalc/cls.h>



#define TEST_CNT		(100000000)
#define TEST_MAXSIZE		(16384)
#define TEST_STEP		(8)
#define SHOW_STEP		(1)
#define ENABLE_SHOW		(0)

DEF_CLS_LIN(lin, 3, 16, 8)

DEF_CLS_POW2B(pow2b, 0, 32)

DEF_CLS_TC(tc, 3, 15)

DEF_CLS_SUPER(super, 4, 16, 2, 4)
DEF_CLS_SUPER_CLS2SZTBL(superc, 4, 16, 2, 4)

DEF_CLS_MI(mi, 0, 16)

#define DEF_CLS_TEST(name, maxsize, testcnt, step)			\
static void test_sz2cls_##name (){\
	struct timespec ts, td;\
	szcls_t *c = (szcls_t *)malloc(sizeof(szcls_t) * maxsize);\
	size_t  *s = (size_t *)malloc(sizeof(size_t) * _clsnr_##name );\
	if (!c || !s){\
		printf("malloc %p and %p, size %lu and %lu\n", c, s, sizeof(szcls_t) * maxsize, sizeof(size_t) * _clsnr_##name );\
	}\
	assert(c); assert(s);\
	szcls_t cur_cls = -1;\
	for (size_t sz = step; sz < maxsize; sz += step){\
		c[sz] = _sz2cls_##name (sz);\
		assert(c[sz] < _clsnr_##name);\
		s[c[sz]] = _cls2sz_##name (c[sz]);\
		if(((cur_cls != c[sz]) || SHOW_STEP) && ENABLE_SHOW) {cur_cls = c[sz]; printf("s%lu -> c%u -> rs%lu\n", sz, c[sz], s[c[sz]]); }\
		/* assert(_sz2cls_##name (s[c[sz]]) == c[sz]); */\
		assert( s[c[sz]] >= sz );\
	}\
	word_t hashseed = rdcnt_relax();\
	TIME_STAMP(&ts);\
	word_t idx = 0;\
	while(idx < testcnt){\
		for (size_t sz = 1; sz < maxsize; sz++, idx++){\
			atm_st(&c[sz], _sz2cls_##name (sz) );\
		}\
	}\
	TIME_STAMP(&td);\
	printf("-------[%s]sz2cls %lu, %llu ms, total cls_nr %u-------\n", #name, (word_t)testcnt, TIME_DELTA_MS(&ts, &td), _clsnr_##name);\
	TIME_STAMP(&ts);\
	idx = 0;\
	hashseed = rdcnt_relax();\
	while(idx < testcnt){\
		for (szcls_t sc = 0; sc < _clsnr_##name; sc++, idx++){\
			atm_st(&s[sc], _cls2sz_##name (sc) ) ;\
		}\
	}\
	TIME_STAMP(&td);\
	printf("-------[%s]cls2sz %lu, %llu ms-------\n", #name, (word_t)testcnt, TIME_DELTA_MS(&ts, &td));\
	free(c); free(s);\
}

DEF_CLS_TEST(lin, TEST_MAXSIZE, TEST_CNT, TEST_STEP)

DEF_CLS_TEST(pow2b, TEST_MAXSIZE, TEST_CNT, TEST_STEP)

DEF_CLS_TEST(tc, TEST_MAXSIZE, TEST_CNT, TEST_STEP)

DEF_CLS_TEST(super, TEST_MAXSIZE, TEST_CNT, TEST_STEP)

DEF_CLS_TEST(superc, TEST_MAXSIZE, TEST_CNT, TEST_STEP)

DEF_CLS_TEST(mi, TEST_MAXSIZE, TEST_CNT, TEST_STEP)

int main(){
	// assert(log2_align(8) == 3);
	// assert(log2_align(16) == 4);
	// assert(next_pow2_clz(7) == 8);
	// assert(next_pow2_clz(255) == 256);
	// // assert(next_pow2_clz(1))
	// // printf("%lu\n", next_pow2_clz(1));
	// assert(next_pow2_clz(2) == 2);
	// assert(next_pow2_clz(3) == 4);
	// assert(l21og2_align(next_pow2_clz(2)) == 1);
	test_sz2cls_lin();
	test_sz2cls_pow2b();
	test_sz2cls_tc();
	/* 这个性能不太行, 需要cls->sz的空间辅助映射或者直接软件辅助映射 */
	test_sz2cls_super();
	test_sz2cls_superc();
	/* 有辅助快速映射cls->sz */
	test_sz2cls_mi();
	return 0;
}